package com.lablabla.parkme;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Dialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.google.ads.*;

public class ParkMeActivity extends MapActivity implements LocationListener {

	private static final String DATABASE_SERVER_URL = "http:/www.parkme.co.il/default.php";
	private static final String PARKING_OPTION_PARKED = "PARKED";
	private static final String PARKING_OPTION_LEFT = "LEFT";
	private static final String PARKING_OPTION_FIND = "FIND";
	private static final String DEFAULT_DISTANCE = "1000";
	private static final String DEFAULT_NUM_OF_RESULTS = "5";

	private AdView adView;
	private MapController mapController;
	private MapView mapView;
	private LocationManager locationManager;
	private Location currentLocation, destinatioWhenRouting = null;
	private GeoPoint currentPoint;
	private Button leftButton, locateButton, parkedButton, settingsButton;
	private String currentTime;

	// Settings variables
	private String distanceFilterString, numOfResultsString;
	private boolean updateOnFlyFlag = false;

	protected boolean isSpacesDrawn = false;
	protected static boolean isRouteDisplayed = false;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		distanceFilterString = loadPreferences("distance", null);
		numOfResultsString = loadPreferences("results", null);
		updateOnFlyFlag = Boolean.valueOf(loadPreferences("update", null));

		leftButton = (Button) findViewById(R.id.leftButton);
		leftButton.setOnClickListener(update);
		locateButton = (Button) findViewById(R.id.findButton);
		locateButton.setOnClickListener(update);
		parkedButton = (Button) findViewById(R.id.parkedButton);
		parkedButton.setOnClickListener(update);
		settingsButton = (Button) findViewById(R.id.settingsButton);
		settingsButton.setOnClickListener(settings);

		adView = new AdView(this, AdSize.BANNER, "k3ffcd6aae0a8d107ae7878b9af96773");
//		LinearLayout layout = (LinearLayout) findViewById(R.id.mainLayout);
//		layout.addView(adView);
//		AdRequest adRequest = new AdRequest();
//		adRequest.addTestDevice(AdRequest.TEST_EMULATOR);
//	    adView.loadAd(adRequest);
//	    AdView adView = (AdView)this.findViewById(R.id.adView);
//	    adView.loadAd(new AdRequest());

		mapView = (MapView) findViewById(R.id.map);
		mapView.setBuiltInZoomControls(true);
		mapView.setSatellite(false);
		mapController = mapView.getController();
		mapController.setZoom(16);

		getLastLocation();
		animateToCurrentLocation();
	}

	private OnClickListener settings = new OnClickListener() {

		public void onClick(View v) {
			final Dialog settingsDialog = new Dialog(ParkMeActivity.this);
			settingsDialog.setContentView(R.layout.settings);
			settingsDialog.setTitle("Settings");
			settingsDialog.setCancelable(true);
			final EditText distanceFilter = (EditText) settingsDialog.findViewById(R.id.distanceFilter);
			final EditText resultNum = (EditText) settingsDialog.findViewById(R.id.numberOfResults);
			Button saveButton = (Button) settingsDialog.findViewById(R.id.saveButton);
			Button cancelButton = (Button) settingsDialog.findViewById(R.id.cancelButton);
			ToggleButton updateOnFlyButton = (ToggleButton) settingsDialog.findViewById(R.id.updateOnFlyButton);

			updateOnFlyButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {

				@Override
				public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
					updateOnFlyFlag = isChecked;
				}
			});
			saveButton.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					savePreferences("results", resultNum.getText().toString());
					savePreferences("distance", distanceFilter.getText().toString());
					savePreferences("update", String.valueOf(updateOnFlyFlag));
					distanceFilterString = distanceFilter.getText().toString();
					numOfResultsString = resultNum.getText().toString();
					settingsDialog.dismiss();
				}
			});

			cancelButton.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					settingsDialog.dismiss();
				}
			});
			loadPreferences("results", resultNum);
			loadPreferences("distance", distanceFilter);
			loadPreferences("update", updateOnFlyButton);
			settingsDialog.show();
		}
	};

	private OnClickListener update = new OnClickListener() {

		public void onClick(View v) {
			if (currentLocation != null) {
				String parkingOption = null;
				double longitude = currentLocation.getLongitude();
				double latitude = currentLocation.getLatitude();
				if (v.getId() == R.id.findButton) {
					parkingOption = PARKING_OPTION_FIND;
				} else if (v.getId() == R.id.leftButton) {
					parkingOption = PARKING_OPTION_LEFT;
				} else if (v.getId() == R.id.parkedButton) {
					parkingOption = PARKING_OPTION_PARKED;
					if (destinatioWhenRouting == null) {
						Toast.makeText(getApplicationContext(),
								getResources().getString(R.string.noParkingSpaceSelected), Toast.LENGTH_LONG)
								.show();
						return;
					}
					longitude = destinatioWhenRouting.getLongitude();
					latitude = destinatioWhenRouting.getLatitude();
				}
				performUpdate(longitude, latitude, parkingOption);
			}
		}
	};

	private void performUpdate(double longitude, double latitude, String parkingOption) {
		StringBuilder sb;
		ArrayList<NameValuePair> coordinatesToSend = new ArrayList<NameValuePair>();
		coordinatesToSend.add(new DoubleNameValuePair("longitude", longitude));
		coordinatesToSend.add(new DoubleNameValuePair("latitude", latitude));
		coordinatesToSend.add(new BasicNameValuePair("parked", parkingOption));
		coordinatesToSend.add(new IntNameValuePair("distanceTo", Integer.valueOf(distanceFilterString)));
		coordinatesToSend.add(new IntNameValuePair("results", Integer.valueOf(numOfResultsString)));

		try {
			HttpClient httpclient = new DefaultHttpClient();
			HttpPost httppost = new HttpPost(DATABASE_SERVER_URL);
			httppost.setEntity(new UrlEncodedFormEntity(coordinatesToSend));
			HttpResponse response = httpclient.execute(httppost);
			HttpEntity entity = response.getEntity();
			InputStream is = null;
			is = entity.getContent();
			String result = null;
			BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);

			sb = new StringBuilder();
			sb.append(reader.readLine() + "\n");
			String line = "";

			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
			is.close();
			reader.close();
			result = sb.toString();
			Log.d("RESULT", result);
			if (parkingOption.equals(PARKING_OPTION_FIND)) {
				JSONArray jArray = new JSONArray(result);
				JSONObject json_data = null;
				double[] tempLong = null;
				double[] tempLat = null;
				String[] time = null;
				GeoPoint[] coordinates = null;
				for (int i = 0; i < jArray.length() - 1; i++) {
					json_data = jArray.getJSONObject(i);
					if (coordinates == null) {
						coordinates = new GeoPoint[jArray.length() - 1];
					}
					if (tempLong == null) {
						tempLong = new double[jArray.length() - 1];
					}
					if (tempLat == null) {
						tempLat = new double[jArray.length() - 1];
					}
					if (time == null) {
						time = new String[jArray.length() - 1];
					}
					tempLong[i] = json_data.getDouble("longitude");
					tempLat[i] = json_data.getDouble("latitude");
					time[i] = json_data.getString("time");
					coordinates[i] = new GeoPoint((int) (tempLat[i] * 1e6), (int) (tempLong[i] * 1e6));
				}
				json_data = jArray.getJSONObject(jArray.length() - 1);
				currentTime = json_data.getString("time");
				drawCoordinates(coordinates, time);
			} else if (parkingOption.equals(PARKING_OPTION_PARKED)) {
				destinatioWhenRouting = null;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void savePreferences(String key, String value) {
		SharedPreferences sharedPreferences = getPreferences(MODE_PRIVATE);
		SharedPreferences.Editor editor = sharedPreferences.edit();
		editor.putString(key, value);
		editor.commit();
	}

	private String loadPreferences(String key, View view) {
		SharedPreferences sharedPreferences = getPreferences(MODE_PRIVATE);
		String savedString = sharedPreferences.getString(key, "");
		if (view == null) {
			if (savedString.equals("")) {
				if (key.equals("distance")) {
					savedString = DEFAULT_DISTANCE;
				} else if (key.equals("results")) {
					savedString = DEFAULT_NUM_OF_RESULTS;
				}
			}
			return savedString;
		}
		if (savedString.equals("")) {
			if (key.equals("distance")) {
				savedString = DEFAULT_DISTANCE;
			} else if (key.equals("results")) {
				savedString = DEFAULT_NUM_OF_RESULTS;
			}
		}
		if (view instanceof EditText) {
			((TextView) view).setText(savedString);
		} else {
			((ToggleButton) view).setChecked(Boolean.valueOf(savedString));
		}
		return "";
	}

	public ParkMeActivity() {
		// TODO Auto-generated constructor stub
	}

	Handler listeningHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			Bundle bundle = msg.getData();
			destinatioWhenRouting = (Location) bundle.getParcelable("destination");
		};
	};

	private void drawSpaces(GeoPoint[] coordinates, String[] time) {
		Drawable marker = getResources().getDrawable(R.drawable.malls);
		PinsOverlay parkingSpaces = new PinsOverlay(marker, mapView, this);
		List<Overlay> spaces = mapView.getOverlays();
		for (int i = 0; i < coordinates.length; i++) {
			long systemTime = Long.valueOf(currentTime);
			long timeSinceReported = (systemTime - Long.valueOf(time[i])) / 60;
			OverlayItem spot = new OverlayItem(coordinates[i], getAddressFromGP(coordinates[i]), getResources()
					.getString(R.string.timeSinceReported)
					+ String.valueOf(timeSinceReported)
					+ " "
					+ getResources().getString(R.string.minutes));
			parkingSpaces.addOverlay(spot);
		}
		spaces.add(parkingSpaces);
		parkingSpaces.setCurrentLocation(currentLocation);
		isSpacesDrawn = true;
	}

	private void drawCoordinates(GeoPoint[] coordinates, String[] time) {
		if (coordinates != null) {
			if (!isSpacesDrawn) {
				drawSpaces(coordinates, time);
			} else {
				mapView.getOverlays().clear();
				isRouteDisplayed = false;
				drawCurrPositionOverlay();
				drawSpaces(coordinates, time);
			}
		} else {
			Toast.makeText(getApplicationContext(), getResources().getString(R.string.noParkingSpaceFound),
					Toast.LENGTH_LONG).show();
			mapView.getOverlays().clear();
			isRouteDisplayed = false;
			drawCurrPositionOverlay();
		}
	}

	private String getAddressFromGP(GeoPoint geoPoint) {
		Location location = PinsOverlay.convertGpToLoc(geoPoint);
		boolean sensor = true;
		String result = null;
		String address = null;
		try {
			HttpClient httpclient = new DefaultHttpClient();

			String url = "http://maps.googleapis.com/maps/api/geocode/json?latlng=" + location.getLatitude() + ","
					+ location.getLongitude() + "&sensor=" + sensor;

			HttpPost httppost = new HttpPost(url);
			HttpResponse response = httpclient.execute(httppost);
			HttpEntity entity = response.getEntity();
			InputStream is = null;
			is = entity.getContent();
			BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);

			StringBuilder sb = new StringBuilder();
			sb.append(reader.readLine() + "\n");
			String line = "0";

			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
			is.close();
			reader.close();
			result = sb.toString();
			JSONObject jsonObject = new JSONObject(result);
			JSONArray resultArray = jsonObject.getJSONArray("results");
			JSONObject addresses = resultArray.getJSONObject(0);
			address = addresses.getString("formatted_address");

		} catch (Exception e) {
			e.printStackTrace();
		}
		return address;
	}

	@Override
	protected void onResume() {
		super.onResume();
		locationManager.requestLocationUpdates(getBestProvider(), 1000, 1, this);
	}

	@Override
	protected void onPause() {
		super.onPause();
		locationManager.removeUpdates(this);
	}

	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return isRouteDisplayed;
	}

	public void getLastLocation() {
		String provider = getBestProvider();
		currentLocation = locationManager.getLastKnownLocation(provider);
		if (currentLocation != null) {
			setCurrentLocation(currentLocation);
		} else {
			Toast.makeText(this, "Location not yet acquired", Toast.LENGTH_LONG).show();
		}
	}

	public void animateToCurrentLocation() {
		if (currentPoint != null) {
			mapController.animateTo(currentPoint);
			drawCurrPositionOverlay();
		}
	}

	public String getBestProvider() {
		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		Criteria criteria = new Criteria();
		criteria.setPowerRequirement(Criteria.NO_REQUIREMENT);
		criteria.setAccuracy(Criteria.NO_REQUIREMENT);
		String bestProvider = locationManager.getBestProvider(criteria, true);
		return bestProvider;
	}

	public void setCurrentLocation(Location location) {
		int currLatitude = (int) (location.getLatitude() * 1E6);
		int currLongitude = (int) (location.getLongitude() * 1E6);
		currentPoint = new GeoPoint(currLatitude, currLongitude);
		currentLocation = location;
	}

	public void centerToCurrentLocation(View view) {
		animateToCurrentLocation();
	}

	public void onLocationChanged(Location location) {
		setCurrentLocation(location);
		if (updateOnFlyFlag) {
			performUpdate(location.getLongitude(), location.getLatitude(), PARKING_OPTION_FIND);
		}
		animateToCurrentLocation();
	}

	public void onProviderDisabled(String provider) {
		// TODO Auto-generated method stub

	}

	public void onProviderEnabled(String provider) {
		// TODO Auto-generated method stub

	}

	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub

	}

	public void drawCurrPositionOverlay() {
		List<Overlay> overlays = mapView.getOverlays();
		PinsOverlay currPos = null;
		overlays.remove(currPos);
		Drawable marker = getResources().getDrawable(R.drawable.me);
		currPos = new PinsOverlay(marker, mapView, this);
		if (currentPoint != null) {
			OverlayItem overlayitem = new OverlayItem(currentPoint, "Current Location", "Your are here");
			currPos.addOverlay(overlayitem);
			overlays.add(currPos);
			currPos.setCurrentLocation(currentLocation);
		}
	}
}